package com.wawu.common.utils;

import com.wawu.common.utils.DruidUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.*;
import java.util.List;

/**
 * 设计初衷：
 *  这个方法只管执行，其他都不管
 * 对于使用者来说：
 *  只需要要传入sql，参数，其他都不管
 */
public class SQLExcutorUtil {
    //获取数据库连接
    private static Connection getConnection() throws SQLException {
        return DruidUtil.getConnection();
    }

    //把参数放在最后就不用新建数组了
    //这里不使用泛型，达不到我想要的效果
    /**
     * 查询单个对象的方法
     * @param sql SQL语句
     * @param resultType 查询结果的类型
     * @param params 查询参数
     * @param <T> 返回的对象类型
     * @return 返回查询的单个结果
     * @throws SQLException
     */
    public static <T> T querySingle(String sql, Class<T> resultType, Object... params) throws SQLException {
        QueryRunner queryRunner = new QueryRunner();
        try (Connection conn = getConnection()) {
            // 使用 BeanHandler 处理单一结果
            return queryRunner.query(conn, sql, new BeanHandler<>(resultType), params);
        }
    }
    /**
     * 查询多个对象的方法，返回一个列表
     * @param sql SQL语句
     * @param resultType 查询结果的类型
     * @param params 查询参数
     * @param <T> 返回的对象类型
     * @return 返回查询的结果列表
     * @throws SQLException
     */
    public static <T> List<T> queryList(String sql, Class<T> resultType, Object... params) throws SQLException {
        QueryRunner queryRunner = new QueryRunner();
        try (Connection conn = getConnection()) {
            // 使用 BeanListHandler 处理多个结果
            return queryRunner.query(conn, sql, new BeanListHandler<>(resultType), params);
        }
    }

    /**
     * 返回单一的标量值
     * @param sql
     * @param resultType
     * @param params
     * @return
     * @param <T>
     * @throws SQLException
     */
    public static <T> T queryScalar(String sql, Class<T> resultType, Object... params) throws SQLException {
        QueryRunner queryRunner = new QueryRunner();
        try (Connection conn = getConnection()) {
            return queryRunner.query(conn, sql, new ScalarHandler<>(), params);
        }
    }


    // 更新操作：INSERT、UPDATE、DELETE
    public static int update(String sql, Object... params) throws SQLException {
        QueryRunner queryRunner = new QueryRunner();
        try (Connection conn = getConnection()) {
            return queryRunner.update(conn, sql, params);
        }
    }

    /**
     * (GPT生成未细看)
     * 执行更新语句，并返回生成的键值（insert）
     * @param sql
     * @param params
     * @return
     * @throws SQLException
     */
    public static long updateAndGetGeneratedKey(String sql, Object... params) throws SQLException {
        QueryRunner queryRunner = new QueryRunner();
        try (Connection conn = getConnection()) {
            // 执行插入语句并获取生成的主键（假设主键是自增的）
            PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            // 设置参数
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i + 1, params[i]);
            }
            // 执行更新
            int affectedRows = ps.executeUpdate();

            // 获取生成的主键
            if (affectedRows > 0) {
                try (ResultSet generatedKeys = ps.getGeneratedKeys()) {
                    if (generatedKeys.next()) {
                        return generatedKeys.getLong(1); // 返回生成的主键
                    }
                }
            }
            return -1; // 没有生成主键
        }
    }


    // 批量操作
    public static int[] batchUpdate(String sql, Object[][] params) throws SQLException {
        QueryRunner queryRunner = new QueryRunner();
        try (Connection conn = getConnection()) {
            return queryRunner.batch(conn, sql, params);
        }
    }

    //TODO 这部分想应该不要放在这里最好，最好还是放在服务层
    // 事务操作（可选）
    public static void transaction(Runnable... operations) throws SQLException {
        try (Connection conn = getConnection()) {
            conn.setAutoCommit(false);
            try {
                for (Runnable operation : operations) {
                    operation.run(); // 执行操作
                }
                conn.commit(); // 提交事务
            } catch (SQLException e) {
                conn.rollback(); // 回滚事务
                throw e;
            }
        }
    }
}

